package com.allwees.bs.c.module.ops.service.impl;

import com.allwees.bs.c.module.ops.entity.CashActiveDefEntity;
import com.allwees.bs.c.module.ops.repository.CashActiveDefRepository;
import com.allwees.bs.c.module.ops.service.CashActiveDefUseService;
import com.allwees.bs.c.module.ops.service.CouponService;
import com.allwees.bs.c.module.ops.vo.AccountStaticVariableVo;
import com.allwees.bs.c.module.order.dto.CartDTO;
import com.allwees.bs.c.module.order.service.CartService;
import com.allwees.bs.c.module.user.entity.UserCashEntity;
import com.allwees.bs.c.module.user.entity.UserCashLogEntity;
import com.allwees.bs.c.module.user.entity.UserEntity;
import com.allwees.bs.c.module.user.repository.UserCashLogRepository;
import com.allwees.bs.c.module.user.repository.UserCashRepository;
import com.allwees.bs.c.module.user.service.IUserService;
import com.allwees.bs.core.model.coupon.constant.ECashLogType;
import com.allwees.bs.core.model.coupon.constant.ECashUseType;
import com.allwees.bs.core.modelbase.exception.BusinessException;
import com.allwees.core.common.constant.EStatus;
import com.allwees.core.common.util.MoneyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.List;

/**
 * @author mouhaining
 * @since 2020-05-20 17:39
 */
@Slf4j
@Service
public class CashActiveDefUseServiceImpl implements CashActiveDefUseService {

    @Autowired
    private CashActiveDefRepository cashActiveDefRepository;
    @Autowired
    private UserCashLogRepository userCashLogRepository;
    @Autowired
    private UserCashRepository userCashRepository;
    @Autowired
    private IUserService userService;
    @Autowired
    private CouponService couponService;
    @Autowired
    private CartService cartService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void use(String userUuid, String relateKey, BigDecimal value) {
        UserCashEntity userCash = userCashRepository.findByUserUuid(userUuid);
        if (userCash == null) {
            log.warn("user account cash is not exist");
            return;
        }
        Assert.isTrue(userCash.getValue().compareTo(value) >= 0, "you cash not enough");
        userCash.setValue(MoneyUtil.sub(userCash.getValue(), value));
        userCashRepository.save(userCash);

        saveLog(userUuid, relateKey, null, value, ECashLogType.ORDER_DEDUCT);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void inviterReceived(String userUuid, ECashUseType useType) {
        UserEntity inviterUser = userService.findInviterUser(userUuid);
        if (inviterUser == null) {
            return;
        }
        receive(inviterUser.getUuid(), userUuid, useType, ECashLogType.INVITE_USER);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refunded(String userUuid, String orderUuid, BigDecimal value) {
        if (value == null || BigDecimal.ZERO.compareTo(value) >= 0) {
            return;
        }
        UserCashEntity userCash = userCashRepository.findByUserUuid(userUuid);
        if (userCash == null) {
            log.warn("user account cash is not exist");
            return;
        }
        userCash.setValue(MoneyUtil.add(userCash.getValue(), value));
        userCashRepository.save(userCash);
        saveLog(userUuid, orderUuid, null, value, ECashLogType.REFUNDED);
    }


    @Override
    public UserCashEntity checkByUserUuid(String userUuid, String cartId, BigDecimal useCash) {

        UserCashEntity currentCash = userCashRepository.findByUserUuid(userUuid);

        CartDTO cartDTO = cartService.getCart(cartId);

        if (cartDTO == null) {
            throw new BusinessException("you cart non exist");
        }

        /**
        if (!useCash.equals(BigDecimal.ZERO) && (currentCash == null || currentCash.getValue().compareTo(cartDTO.getAmt()) < 0)) {
            throw new BusinessException("you cash not enough");
        }**/

        if (!currentCash.getUserUuid().equals(cartDTO.getUserUuid())) {
            throw new BusinessException("you cart non exist,cartId error");
        }

        return currentCash;
    }


    @Override
    public AccountStaticVariableVo staticVariable() {
        AccountStaticVariableVo staticVariable = new AccountStaticVariableVo();

        CashActiveDefEntity casActiveDef = cashActiveDefRepository.findByUseType(ECashUseType.SYSTEM_INVITEOR_RECEIVED);

        staticVariable.setMaxInviteRewardCashAmt(MoneyUtil.mul(BigDecimal.valueOf(casActiveDef.getSingleUserReceiveMaxCount()), casActiveDef.getValue()));
        staticVariable.setSingleInviteRewardCashAmt(casActiveDef.getValue());
        staticVariable.setSignInExchangeDeductAmt(couponService.findSignInMinDeductAmt());
        return staticVariable;
    }

    private void receive(String userUuid, String relateKey, ECashUseType useType, ECashLogType logType) {
        CashActiveDefEntity cashActiveDef = cashActiveDefRepository.findByUseType(useType);
        if (cashActiveDef == null) {
            return;
        }
        receive(userUuid, relateKey, cashActiveDef.getUuid(), logType);
    }

    private void receive(String userUuid, String relateKey, String cashActiveUuid, ECashLogType logType) {
        CashActiveDefEntity cashActiveDef = checkCashActiveDef(cashActiveUuid);

        List<UserCashLogEntity> userCashs = userCashLogRepository.findCountByUserUuidAndCashActiveUuid(userUuid, cashActiveUuid);
        if (cashActiveDef.getSingleUserReceiveMaxCount() != null && cashActiveDef.getSingleUserReceiveMaxCount() <= userCashs.size()) {
            throw new BusinessException("receive count exceeded max count");
        }

        UserCashEntity userCash = userCashRepository.findByUserUuid(userUuid);
        if (userCash == null) {
            userCash = ofUserCash(userUuid, cashActiveDef);
        }
        userCash.setValue(MoneyUtil.add(userCash.getValue(), cashActiveDef.getValue()));
        userCashRepository.save(userCash);

        saveLog(userUuid, relateKey, cashActiveUuid, cashActiveDef.getValue(), logType);
    }

    private CashActiveDefEntity checkCashActiveDef(String cashActiveUuid) {
        CashActiveDefEntity cashActiveDef = cashActiveDefRepository.getByUuid(cashActiveUuid);
        if (!EStatus.NORMAL.value().equals(cashActiveDef.getStatus())) {
            throw new BusinessException("cash active [" + cashActiveUuid + "] disabled");
        }
        return cashActiveDef;
    }

    private static UserCashEntity ofUserCash(String userUuid, CashActiveDefEntity cashActiveDef) {
        UserCashEntity userCash = new UserCashEntity(cashActiveDef);
        userCash.setUserUuid(userUuid);
        return userCash;
    }


    /**
     * 保存资金变更日志
     *
     * @param userUuid
     * @param relateKey
     * @param cashActiveUuid
     * @param value
     * @param logType
     */
    private void saveLog(String userUuid, String relateKey, String cashActiveUuid, BigDecimal value, ECashLogType logType) {
        UserCashLogEntity userCashLog = new UserCashLogEntity();
        userCashLog.setUserUuid(userUuid);
        userCashLog.setCashActiveUuid(cashActiveUuid);
        userCashLog.setValue(value);
        userCashLog.setLogType(logType);
        userCashLog.setRelateKey(relateKey);
        userCashLogRepository.save(userCashLog);
    }
}
